{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "04dGdK2VftUM"
   },
   "source": [
    "# AI Meme Creator Agent"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "xUTYMeY9fvUA"
   },
   "source": [
    "* An AI agent that generates memes using browser automation and multiple LLM models.\n",
    "* The agent can create custom memes based on user prompts by navigating to meme creation websites, selecting templates, and generating captions.\n",
    "* Features include multi-model support (Claude, Deepseek, OpenAI), browser automation, template selection, and automatic meme generation with direct image links."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "_hI9XGsJicU8"
   },
   "source": [
    "[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Dhivya-Bharathy/PraisonAI/blob/main/examples/cookbooks/ai_meme_creator_agent.ipynb)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "6rrl-ZHqgCj2"
   },
   "source": [
    "# Dependencies"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "pP9B-OsCgDpr"
   },
   "outputs": [],
   "source": [
    "!pip install praisonai streamlit browser-use langchain-openai langchain-anthropic langchain-core"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Xe0_c_lig5YJ"
   },
   "source": [
    "# Setup Key"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "fsVpWSVHg64O",
    "outputId": "74d0ee0f-a3e2-413c-98cd-a410888eedb3"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✅ API keys configured!\n",
      "✅ Using model: OpenAI\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "\n",
    "# Set your API keys\n",
    "openai_key = \"Enter you api key here\"\n",
    "anthropic_key = \"Enter you api key here\"  # Get from https://console.anthropic.com\n",
    "deepseek_key = \"Enter you api key here\"    # Get from https://platform.deepseek.com\n",
    "\n",
    "# Set environment variables\n",
    "os.environ[\"OPENAI_API_KEY\"] = openai_key\n",
    "os.environ[\"ANTHROPIC_API_KEY\"] = anthropic_key\n",
    "os.environ[\"DEEPSEEK_API_KEY\"] = deepseek_key\n",
    "\n",
    "# Model selection\n",
    "model_choice = \"OpenAI\"  # Options: \"OpenAI\", \"Claude\", \"Deepseek\"\n",
    "\n",
    "print(\"✅ API keys configured!\")\n",
    "print(f\"✅ Using model: {model_choice}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "rtqdR4Odhexu"
   },
   "source": [
    "# Tools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "id": "I9uC9c97hgYg"
   },
   "outputs": [],
   "source": [
    "# Custom Meme Template Search Tool\n",
    "import requests\n",
    "from typing import Dict, Any, List\n",
    "import re\n",
    "\n",
    "class MemeTemplateSearchTool:\n",
    "    def __init__(self):\n",
    "        self.base_url = \"https://imgflip.com\"\n",
    "        self.popular_templates = [\n",
    "            \"distracted-boyfriend\", \"two-buttons\", \"one-does-not-simply\",\n",
    "            \"drake-hotline-bling\", \"change-my-mind\", \"ancient-aliens\",\n",
    "            \"y-u-no\", \"success-kid\", \"first-world-problems\", \"futurama-fry\"\n",
    "        ]\n",
    "\n",
    "    def search_templates(self, query: str) -> Dict[str, Any]:\n",
    "        \"\"\"Search for meme templates based on query\"\"\"\n",
    "        try:\n",
    "            # Extract key action words from query\n",
    "            action_words = self._extract_action_words(query.lower())\n",
    "\n",
    "            # Find relevant templates\n",
    "            relevant_templates = []\n",
    "            for template in self.popular_templates:\n",
    "                if any(word in template for word in action_words):\n",
    "                    relevant_templates.append(template)\n",
    "\n",
    "            # If no direct matches, return popular templates\n",
    "            if not relevant_templates:\n",
    "                relevant_templates = self.popular_templates[:5]\n",
    "\n",
    "            return {\n",
    "                \"success\": True,\n",
    "                \"query\": query,\n",
    "                \"action_words\": action_words,\n",
    "                \"suggested_templates\": relevant_templates,\n",
    "                \"template_urls\": [f\"{self.base_url}/{template}\" for template in relevant_templates]\n",
    "            }\n",
    "        except Exception as e:\n",
    "            return {\"error\": f\"Error searching templates: {str(e)}\"}\n",
    "\n",
    "    def _extract_action_words(self, text: str) -> List[str]:\n",
    "        \"\"\"Extract action words from text\"\"\"\n",
    "        action_words = [\n",
    "            \"laugh\", \"cry\", \"smile\", \"angry\", \"surprised\", \"confused\",\n",
    "            \"happy\", \"sad\", \"excited\", \"worried\", \"thinking\", \"shocked\",\n",
    "            \"bully\", \"fight\", \"work\", \"study\", \"sleep\", \"eat\", \"drink\",\n",
    "            \"run\", \"walk\", \"sit\", \"stand\", \"look\", \"watch\", \"listen\"\n",
    "        ]\n",
    "\n",
    "        found_words = []\n",
    "        for word in action_words:\n",
    "            if word in text:\n",
    "                found_words.append(word)\n",
    "\n",
    "        return found_words\n",
    "\n",
    "# Custom Caption Generator Tool\n",
    "import random\n",
    "\n",
    "class CaptionGeneratorTool:\n",
    "    def __init__(self):\n",
    "        self.caption_styles = {\n",
    "            \"setup_punchline\": \"Top: {setup}\\nBottom: {punchline}\",\n",
    "            \"comparison\": \"Top: {option1}\\nBottom: {option2}\",\n",
    "            \"reaction\": \"Top: {situation}\\nBottom: {reaction}\",\n",
    "            \"confession\": \"Top: {confession}\\nBottom: {reality}\"\n",
    "        }\n",
    "\n",
    "    def generate_captions(self, query: str, template: str) -> Dict[str, Any]:\n",
    "        \"\"\"Generate meme captions based on query and template\"\"\"\n",
    "        try:\n",
    "            # Analyze query for meme type\n",
    "            meme_type = self._analyze_meme_type(query)\n",
    "\n",
    "            # Generate captions based on type\n",
    "            if meme_type == \"comparison\":\n",
    "                captions = self._generate_comparison_captions(query)\n",
    "            elif meme_type == \"reaction\":\n",
    "                captions = self._generate_reaction_captions(query)\n",
    "            elif meme_type == \"confession\":\n",
    "                captions = self._generate_confession_captions(query)\n",
    "            else:\n",
    "                captions = self._generate_setup_punchline_captions(query)\n",
    "\n",
    "            return {\n",
    "                \"success\": True,\n",
    "                \"query\": query,\n",
    "                \"template\": template,\n",
    "                \"meme_type\": meme_type,\n",
    "                \"captions\": captions,\n",
    "                \"suggested_style\": self.caption_styles.get(meme_type, self.caption_styles[\"setup_punchline\"])\n",
    "            }\n",
    "        except Exception as e:\n",
    "            return {\"error\": f\"Error generating captions: {str(e)}\"}\n",
    "\n",
    "    def _analyze_meme_type(self, query: str) -> str:\n",
    "        \"\"\"Analyze query to determine meme type\"\"\"\n",
    "        query_lower = query.lower()\n",
    "\n",
    "        if any(word in query_lower for word in [\"vs\", \"versus\", \"or\", \"either\", \"choose\"]):\n",
    "            return \"comparison\"\n",
    "        elif any(word in query_lower for word in [\"when\", \"reaction\", \"face\", \"look\"]):\n",
    "            return \"reaction\"\n",
    "        elif any(word in query_lower for word in [\"confess\", \"secret\", \"actually\", \"truth\"]):\n",
    "            return \"confession\"\n",
    "        else:\n",
    "            return \"setup_punchline\"\n",
    "\n",
    "    def _generate_setup_punchline_captions(self, query: str) -> List[Dict[str, str]]:\n",
    "        \"\"\"Generate setup-punchline style captions\"\"\"\n",
    "        captions = []\n",
    "\n",
    "        # Extract key elements from query\n",
    "        words = query.split()\n",
    "        if len(words) >= 3:\n",
    "            # Create variations\n",
    "            captions.append({\n",
    "                \"top\": f\"When {query}\",\n",
    "                \"bottom\": \"But it actually works\"\n",
    "            })\n",
    "            captions.append({\n",
    "                \"top\": f\"Me trying to {query}\",\n",
    "                \"bottom\": \"Reality: Complete failure\"\n",
    "            })\n",
    "            captions.append({\n",
    "                \"top\": f\"Everyone: {query}\",\n",
    "                \"bottom\": \"Me: *confused*\"\n",
    "            })\n",
    "\n",
    "        return captions\n",
    "\n",
    "    def _generate_comparison_captions(self, query: str) -> List[Dict[str, str]]:\n",
    "        \"\"\"Generate comparison style captions\"\"\"\n",
    "        captions = []\n",
    "\n",
    "        captions.append({\n",
    "            \"top\": \"What I think will happen\",\n",
    "            \"bottom\": \"What actually happens\"\n",
    "        })\n",
    "        captions.append({\n",
    "            \"top\": \"The plan\",\n",
    "            \"bottom\": \"The execution\"\n",
    "        })\n",
    "        captions.append({\n",
    "            \"top\": \"Before\",\n",
    "            \"bottom\": \"After\"\n",
    "        })\n",
    "\n",
    "        return captions\n",
    "\n",
    "    def _generate_reaction_captions(self, query: str) -> List[Dict[str, str]]:\n",
    "        \"\"\"Generate reaction style captions\"\"\"\n",
    "        captions = []\n",
    "\n",
    "        captions.append({\n",
    "            \"top\": f\"When {query}\",\n",
    "            \"bottom\": \"My face: 😱\"\n",
    "        })\n",
    "        captions.append({\n",
    "            \"top\": f\"Me: {query}\",\n",
    "            \"bottom\": \"Also me: *surprised pikachu*\"\n",
    "        })\n",
    "\n",
    "        return captions\n",
    "\n",
    "    def _generate_confession_captions(self, query: str) -> List[Dict[str, str]]:\n",
    "        \"\"\"Generate confession style captions\"\"\"\n",
    "        captions = []\n",
    "\n",
    "        captions.append({\n",
    "            \"top\": f\"I confess: {query}\",\n",
    "            \"bottom\": \"But I'm not sorry\"\n",
    "        })\n",
    "        captions.append({\n",
    "            \"top\": f\"Everyone thinks {query}\",\n",
    "            \"bottom\": \"But actually...\"\n",
    "        })\n",
    "\n",
    "        return captions\n",
    "\n",
    "# Custom Meme Validation Tool\n",
    "class MemeValidationTool:\n",
    "    def __init__(self):\n",
    "        self.validation_criteria = {\n",
    "            \"humor\": [\"funny\", \"amusing\", \"entertaining\"],\n",
    "            \"relevance\": [\"related\", \"connected\", \"appropriate\"],\n",
    "            \"clarity\": [\"clear\", \"understandable\", \"readable\"],\n",
    "            \"creativity\": [\"original\", \"creative\", \"unique\"]\n",
    "        }\n",
    "\n",
    "    def validate_meme(self, query: str, captions: List[Dict[str, str]], template: str) -> Dict[str, Any]:\n",
    "        \"\"\"Validate meme quality and suggest improvements\"\"\"\n",
    "        try:\n",
    "            scores = {}\n",
    "            suggestions = []\n",
    "\n",
    "            # Check humor\n",
    "            humor_score = self._check_humor(query, captions)\n",
    "            scores[\"humor\"] = humor_score\n",
    "            if humor_score < 0.7:\n",
    "                suggestions.append(\"Consider making the punchline more unexpected or relatable\")\n",
    "\n",
    "            # Check relevance\n",
    "            relevance_score = self._check_relevance(query, captions)\n",
    "            scores[\"relevance\"] = relevance_score\n",
    "            if relevance_score < 0.8:\n",
    "                suggestions.append(\"Ensure captions directly relate to the query topic\")\n",
    "\n",
    "            # Check clarity\n",
    "            clarity_score = self._check_clarity(captions)\n",
    "            scores[\"clarity\"] = clarity_score\n",
    "            if clarity_score < 0.9:\n",
    "                suggestions.append(\"Make sure text is short and easy to read\")\n",
    "\n",
    "            # Check creativity\n",
    "            creativity_score = self._check_creativity(query, captions)\n",
    "            scores[\"creativity\"] = creativity_score\n",
    "            if creativity_score < 0.6:\n",
    "                suggestions.append(\"Try a more unique angle or unexpected twist\")\n",
    "\n",
    "            # Overall score\n",
    "            overall_score = sum(scores.values()) / len(scores)\n",
    "\n",
    "            return {\n",
    "                \"success\": True,\n",
    "                \"scores\": scores,\n",
    "                \"overall_score\": overall_score,\n",
    "                \"suggestions\": suggestions,\n",
    "                \"quality\": \"Excellent\" if overall_score >= 0.8 else \"Good\" if overall_score >= 0.6 else \"Needs Improvement\"\n",
    "            }\n",
    "        except Exception as e:\n",
    "            return {\"error\": f\"Error validating meme: {str(e)}\"}\n",
    "\n",
    "    def _check_humor(self, query: str, captions: List[Dict[str, str]]) -> float:\n",
    "        \"\"\"Check humor quality\"\"\"\n",
    "        # Simple heuristic - check for contrast, exaggeration, or relatable elements\n",
    "        score = 0.5  # Base score\n",
    "\n",
    "        for caption in captions:\n",
    "            text = f\"{caption.get('top', '')} {caption.get('bottom', '')}\".lower()\n",
    "\n",
    "            # Check for humor indicators\n",
    "            if any(word in text for word in [\"but\", \"however\", \"actually\", \"reality\"]):\n",
    "                score += 0.2  # Contrast\n",
    "            if any(word in text for word in [\"everyone\", \"nobody\", \"always\", \"never\"]):\n",
    "                score += 0.1  # Exaggeration\n",
    "            if any(word in text for word in [\"me\", \"my\", \"i\", \"we\"]):\n",
    "                score += 0.1  # Relatable\n",
    "\n",
    "        return min(1.0, score)\n",
    "\n",
    "    def _check_relevance(self, query: str, captions: List[Dict[str, str]]) -> float:\n",
    "        \"\"\"Check relevance to query\"\"\"\n",
    "        query_words = set(query.lower().split())\n",
    "        score = 0.5  # Base score\n",
    "\n",
    "        for caption in captions:\n",
    "            caption_text = f\"{caption.get('top', '')} {caption.get('bottom', '')}\".lower()\n",
    "            caption_words = set(caption_text.split())\n",
    "\n",
    "            # Check word overlap\n",
    "            overlap = len(query_words.intersection(caption_words))\n",
    "            if overlap > 0:\n",
    "                score += 0.3\n",
    "            if overlap > 2:\n",
    "                score += 0.2\n",
    "\n",
    "        return min(1.0, score)\n",
    "\n",
    "    def _check_clarity(self, captions: List[Dict[str, str]]) -> float:\n",
    "        \"\"\"Check text clarity and readability\"\"\"\n",
    "        score = 1.0  # Start with perfect score\n",
    "\n",
    "        for caption in captions:\n",
    "            top_text = caption.get('top', '')\n",
    "            bottom_text = caption.get('bottom', '')\n",
    "\n",
    "            # Penalize long text\n",
    "            if len(top_text) > 50:\n",
    "                score -= 0.1\n",
    "            if len(bottom_text) > 50:\n",
    "                score -= 0.1\n",
    "\n",
    "            # Penalize complex words\n",
    "            complex_words = [word for word in top_text.split() if len(word) > 10]\n",
    "            if len(complex_words) > 0:\n",
    "                score -= 0.1\n",
    "\n",
    "        return max(0.0, score)\n",
    "\n",
    "    def _check_creativity(self, query: str, captions: List[Dict[str, str]]) -> float:\n",
    "        \"\"\"Check creativity and originality\"\"\"\n",
    "        score = 0.5  # Base score\n",
    "\n",
    "        # Check for common meme phrases (penalize)\n",
    "        common_phrases = [\n",
    "            \"surprised pikachu\", \"change my mind\", \"one does not simply\",\n",
    "            \"ancient aliens\", \"distracted boyfriend\", \"drake\"\n",
    "        ]\n",
    "\n",
    "        for caption in captions:\n",
    "            caption_text = f\"{caption.get('top', '')} {caption.get('bottom', '')}\".lower()\n",
    "\n",
    "            # Reward for avoiding common phrases\n",
    "            if not any(phrase in caption_text for phrase in common_phrases):\n",
    "                score += 0.3\n",
    "\n",
    "            # Reward for unique word combinations\n",
    "            unique_words = len(set(caption_text.split()))\n",
    "            if unique_words > 8:\n",
    "                score += 0.2\n",
    "\n",
    "        return min(1.0, score)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "MnaRLR7rhkxd"
   },
   "source": [
    "# YAML Prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "gfjRa17thl_i",
    "outputId": "09440897-7b9a-4b04-f535-55abf1240e5c"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✅ YAML Prompt configured!\n"
     ]
    }
   ],
   "source": [
    "# YAML Prompt\n",
    "yaml_prompt = \"\"\"\n",
    "name: \"AI Meme Creator Agent\"\n",
    "description: \"Expert meme generator with browser automation and multi-model support\"\n",
    "instructions:\n",
    "  - \"You are an expert meme creator that generates funny and relevant memes based on user prompts\"\n",
    "  - \"Use browser automation to navigate meme creation websites and select appropriate templates\"\n",
    "  - \"Generate creative captions that match the meme template and user's request\"\n",
    "  - \"Ensure memes are humorous, relevant, and visually appealing\"\n",
    "  - \"Provide multiple caption options for different meme styles\"\n",
    "  - \"Validate meme quality and suggest improvements when needed\"\n",
    "  - \"Use appropriate meme templates that fit the context and emotion\"\n",
    "  - \"Create captions that are short, readable, and impactful\"\n",
    "  - \"Consider current trends and popular meme formats\"\n",
    "\n",
    "tools:\n",
    "  - name: \"MemeTemplateSearchTool\"\n",
    "    description: \"Searches for appropriate meme templates based on user query and action words\"\n",
    "  - name: \"CaptionGeneratorTool\"\n",
    "    description: \"Generates creative captions for memes based on query, template, and meme type\"\n",
    "  - name: \"MemeValidationTool\"\n",
    "    description: \"Validates meme quality and provides suggestions for improvement\"\n",
    "\n",
    "output_format:\n",
    "  - \"Provide the generated meme image URL\"\n",
    "  - \"Include caption suggestions and template recommendations\"\n",
    "  - \"Offer quality assessment and improvement tips\"\n",
    "  - \"Explain the meme concept and why it works\"\n",
    "  - \"Provide alternative caption options if available\"\n",
    "\n",
    "temperature: 0.7\n",
    "max_tokens: 3000\n",
    "model: \"gpt-5-nano\"\n",
    "\"\"\"\n",
    "\n",
    "print(\"✅ YAML Prompt configured!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "BlJzii7Whtro"
   },
   "source": [
    "# Main"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "eMA38MJvhvJC",
    "outputId": "744230d3-7fce-444f-af78-7bdb98aa8a61"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "🥸 AI Meme Creator Agent\n",
      "Generate hilarious memes using AI and browser automation!\n",
      "\n",
      "⚙️ Model Configuration\n",
      "✅ Using model: OpenAI\n",
      "\n",
      "🎨 Meme Creation Interface\n",
      "Enter your meme idea:\n",
      "Meme Idea: When you finally understand the code after 3 hours of debugging\n",
      "\n",
      "🚀 Generating meme for: 'When you finally understand the code after 3 hours of debugging'\n",
      "\n",
      "🔍 Step 1: Searching for meme templates...\n",
      "✅ Found 5 relevant templates\n",
      "Action words: stand\n",
      "\n",
      "✍️ Step 2: Generating captions...\n",
      "✅ Generated 2 caption options\n",
      "Meme type: reaction\n",
      "\n",
      "📝 Caption Options:\n",
      "Option 1:\n",
      "  Top: When When you finally understand the code after 3 hours of debugging\n",
      "  Bottom: My face: 😱\n",
      "Option 2:\n",
      "  Top: Me: When you finally understand the code after 3 hours of debugging\n",
      "  Bottom: Also me: *surprised pikachu*\n",
      "\n",
      "�� Step 3: Validating meme quality...\n",
      "✅ Quality Assessment: Excellent\n",
      "Overall Score: 0.88/1.0\n",
      "💡 Suggestions for improvement:\n",
      "  - Make sure text is short and easy to read\n",
      "\n",
      "�� Step 4: Generating meme with browser automation...\n",
      "🔄 Starting browser automation...\n",
      "Error in meme generation: \"ChatOpenAI\" object has no field \"ainvoke\"\n",
      "❌ Failed to generate meme. This might be due to:\n",
      "  - Browser automation issues\n",
      "  - Website changes\n",
      "  - Network connectivity\n",
      "  - API rate limits\n",
      "\n",
      "💡 Manual Meme Creation Instructions:\n",
      "1. Go to https://imgflip.com/memetemplates\n",
      "2. Search for a template related to your query\n",
      "3. Use one of the generated captions:\n",
      "   Option 1: Top='When When you finally understand the code after 3 hours of debugging', Bottom='My face: 😱'\n",
      "   Option 2: Top='Me: When you finally understand the code after 3 hours of debugging', Bottom='Also me: *surprised pikachu*'\n",
      "\n",
      "🧪 Sample Meme Ideas for Testing\n",
      "Try these sample ideas:\n",
      "1. When you finally understand the code after 3 hours of debugging\n",
      "2. Me trying to explain AI to my grandparents\n",
      "3. The difference between what I plan to do vs what I actually do\n",
      "4. When someone asks if I'm free this weekend\n",
      "5. My brain at 3 AM thinking about that embarrassing thing from 5 years ago\n",
      "\n",
      "==================================================\n",
      "�� Powered by AI Meme Creator Agent | Built with PraisonAI\n"
     ]
    }
   ],
   "source": [
    "import asyncio\n",
    "import streamlit as st\n",
    "from browser_use import Agent, SystemPrompt\n",
    "from langchain_openai import ChatOpenAI\n",
    "from langchain_anthropic import ChatAnthropic\n",
    "from langchain_core.messages import HumanMessage\n",
    "import re\n",
    "import os\n",
    "from typing import Dict, Any, List\n",
    "\n",
    "# Initialize tools\n",
    "template_tool = MemeTemplateSearchTool()\n",
    "caption_tool = CaptionGeneratorTool()\n",
    "validation_tool = MemeValidationTool()\n",
    "\n",
    "print(\"🥸 AI Meme Creator Agent\")\n",
    "print(\"Generate hilarious memes using AI and browser automation!\")\n",
    "\n",
    "# Model configuration\n",
    "print(\"\\n⚙️ Model Configuration\")\n",
    "model_choice = \"OpenAI\"  # Options: \"OpenAI\", \"Claude\", \"Deepseek\"\n",
    "print(f\"✅ Using model: {model_choice}\")\n",
    "\n",
    "# Meme generation function\n",
    "async def generate_meme(query: str, model_choice: str, api_key: str) -> str:\n",
    "    \"\"\"Generate meme using browser automation\"\"\"\n",
    "    try:\n",
    "        # Initialize the appropriate LLM based on user selection\n",
    "        if model_choice == \"Claude\":\n",
    "            llm = ChatAnthropic(\n",
    "                model=\"claude-3-5-sonnet-20241022\",\n",
    "                api_key=api_key\n",
    "            )\n",
    "        elif model_choice == \"Deepseek\":\n",
    "            llm = ChatOpenAI(\n",
    "                base_url='https://api.deepseek.com/v1',\n",
    "                model='deepseek-chat',\n",
    "                api_key=api_key,\n",
    "                temperature=0.3\n",
    "            )\n",
    "        else:  # OpenAI\n",
    "            llm = ChatOpenAI(\n",
    "                model=\"gpt-5-nano\",\n",
    "                api_key=api_key,\n",
    "                temperature=0.0\n",
    "            )\n",
    "\n",
    "        task_description = (\n",
    "            \"You are a meme generator expert. You are given a query and you need to generate a meme for it.\\n\"\n",
    "            \"1. Go to https://imgflip.com/memetemplates \\n\"\n",
    "            \"2. Click on the Search bar in the middle and search for ONLY ONE MAIN ACTION VERB (like 'bully', 'laugh', 'cry') in this query: '{0}'\\n\"\n",
    "            \"3. Choose any meme template that metaphorically fits the meme topic: '{0}'\\n\"\n",
    "            \"   by clicking on the 'Add Caption' button below it\\n\"\n",
    "            \"4. Write a Top Text (setup/context) and Bottom Text (punchline/outcome) related to '{0}'.\\n\"\n",
    "            \"5. Check the preview making sure it is funny and a meaningful meme. Adjust text directly if needed. \\n\"\n",
    "            \"6. Look at the meme and text on it, if it doesnt make sense, PLEASE retry by filling the text boxes with different text. \\n\"\n",
    "            \"7. Click on the Generate meme button to generate the meme\\n\"\n",
    "            \"8. Copy the image link and give it as the output\\n\"\n",
    "        ).format(query)\n",
    "\n",
    "        agent = Agent(\n",
    "            task=task_description,\n",
    "            llm=llm,\n",
    "            max_actions_per_step=5,\n",
    "            max_failures=25,\n",
    "            use_vision=(model_choice != \"Deepseek\")\n",
    "        )\n",
    "\n",
    "        history = await agent.run()\n",
    "\n",
    "        # Extract final result from agent history\n",
    "        final_result = history.final_result()\n",
    "\n",
    "        # Use regex to find the meme URL in the result\n",
    "        url_match = re.search(r'https://imgflip\\.com/i/(\\w+)', final_result)\n",
    "        if url_match:\n",
    "            meme_id = url_match.group(1)\n",
    "            return f\"https://i.imgflip.com/{meme_id}.jpg\"\n",
    "        return None\n",
    "    except Exception as e:\n",
    "        print(f\"Error in meme generation: {str(e)}\")\n",
    "        return None\n",
    "\n",
    "# Interactive meme creation\n",
    "print(\"\\n🎨 Meme Creation Interface\")\n",
    "print(\"Enter your meme idea:\")\n",
    "\n",
    "query = input(\"Meme Idea: \")\n",
    "\n",
    "if query.strip():\n",
    "    print(f\"\\n🚀 Generating meme for: '{query}'\")\n",
    "\n",
    "    # Step 1: Search for templates\n",
    "    print(\"\\n🔍 Step 1: Searching for meme templates...\")\n",
    "    template_result = template_tool.search_templates(query)\n",
    "\n",
    "    if \"error\" not in template_result:\n",
    "        print(f\"✅ Found {len(template_result['suggested_templates'])} relevant templates\")\n",
    "        print(f\"Action words: {', '.join(template_result['action_words'])}\")\n",
    "\n",
    "        # Step 2: Generate captions\n",
    "        print(\"\\n✍️ Step 2: Generating captions...\")\n",
    "        selected_template = template_result['suggested_templates'][0]\n",
    "        caption_result = caption_tool.generate_captions(query, selected_template)\n",
    "\n",
    "        if \"error\" not in caption_result:\n",
    "            print(f\"✅ Generated {len(caption_result['captions'])} caption options\")\n",
    "            print(f\"Meme type: {caption_result['meme_type']}\")\n",
    "\n",
    "            # Display caption options\n",
    "            print(\"\\n📝 Caption Options:\")\n",
    "            for i, caption in enumerate(caption_result['captions'], 1):\n",
    "                print(f\"Option {i}:\")\n",
    "                print(f\"  Top: {caption.get('top', 'N/A')}\")\n",
    "                print(f\"  Bottom: {caption.get('bottom', 'N/A')}\")\n",
    "\n",
    "            # Step 3: Validate meme quality\n",
    "            print(\"\\n�� Step 3: Validating meme quality...\")\n",
    "            validation_result = validation_tool.validate_meme(\n",
    "                query, caption_result['captions'], selected_template\n",
    "            )\n",
    "\n",
    "            if \"error\" not in validation_result:\n",
    "                print(f\"✅ Quality Assessment: {validation_result['quality']}\")\n",
    "                print(f\"Overall Score: {validation_result['overall_score']:.2f}/1.0\")\n",
    "\n",
    "                if validation_result['suggestions']:\n",
    "                    print(\"💡 Suggestions for improvement:\")\n",
    "                    for suggestion in validation_result['suggestions']:\n",
    "                        print(f\"  - {suggestion}\")\n",
    "\n",
    "            # Step 4: Generate actual meme (if API key is available)\n",
    "            print(\"\\n�� Step 4: Generating meme with browser automation...\")\n",
    "\n",
    "            # Check if we have the required API key\n",
    "            api_key = os.getenv(\"OPENAI_API_KEY\")\n",
    "            if api_key and api_key != \"your_openai_key_here\":\n",
    "                try:\n",
    "                    print(\"🔄 Starting browser automation...\")\n",
    "                    meme_url = await generate_meme(query, model_choice, api_key)\n",
    "\n",
    "                    if meme_url:\n",
    "                        print(\"✅ Meme Generated Successfully!\")\n",
    "                        print(f\"📸 Meme URL: {meme_url}\")\n",
    "                        print(f\"�� Direct Link: {meme_url}\")\n",
    "\n",
    "                        # Display meme (in Colab, we can use HTML)\n",
    "                        from IPython.display import Image, display\n",
    "                        display(Image(url=meme_url))\n",
    "                    else:\n",
    "                        print(\"❌ Failed to generate meme. This might be due to:\")\n",
    "                        print(\"  - Browser automation issues\")\n",
    "                        print(\"  - Website changes\")\n",
    "                        print(\"  - Network connectivity\")\n",
    "                        print(\"  - API rate limits\")\n",
    "\n",
    "                        # Provide manual instructions\n",
    "                        print(\"\\n💡 Manual Meme Creation Instructions:\")\n",
    "                        print(\"1. Go to https://imgflip.com/memetemplates\")\n",
    "                        print(\"2. Search for a template related to your query\")\n",
    "                        print(\"3. Use one of the generated captions:\")\n",
    "                        for i, caption in enumerate(caption_result['captions'], 1):\n",
    "                            print(f\"   Option {i}: Top='{caption.get('top', '')}', Bottom='{caption.get('bottom', '')}'\")\n",
    "\n",
    "                except Exception as e:\n",
    "                    print(f\"❌ Error during meme generation: {str(e)}\")\n",
    "                    print(\"💡 Try using the manual instructions above\")\n",
    "            else:\n",
    "                print(\"⚠️ API key not configured for browser automation\")\n",
    "                print(\"💡 Using generated captions for manual meme creation:\")\n",
    "                for i, caption in enumerate(caption_result['captions'], 1):\n",
    "                    print(f\"   Option {i}: Top='{caption.get('top', '')}', Bottom='{caption.get('bottom', '')}'\")\n",
    "        else:\n",
    "            print(f\"❌ Error generating captions: {caption_result['error']}\")\n",
    "    else:\n",
    "        print(f\"❌ Error searching templates: {template_result['error']}\")\n",
    "\n",
    "else:\n",
    "    print(\"❌ No meme idea provided.\")\n",
    "\n",
    "print(\"\\n🧪 Sample Meme Ideas for Testing\")\n",
    "sample_ideas = [\n",
    "    \"When you finally understand the code after 3 hours of debugging\",\n",
    "    \"Me trying to explain AI to my grandparents\",\n",
    "    \"The difference between what I plan to do vs what I actually do\",\n",
    "    \"When someone asks if I'm free this weekend\",\n",
    "    \"My brain at 3 AM thinking about that embarrassing thing from 5 years ago\"\n",
    "]\n",
    "\n",
    "print(\"Try these sample ideas:\")\n",
    "for i, idea in enumerate(sample_ideas, 1):\n",
    "    print(f\"{i}. {idea}\")\n",
    "\n",
    "print(\"\\n\" + \"=\"*50)\n",
    "print(\"�� Powered by AI Meme Creator Agent | Built with PraisonAI\")"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
